#include "ring.h"

#include <stddef.h>
#include <assert.h>
#include <string.h>

static void
test()
{
    Ring_T ring = Ring_ring("hello", "how", "are", "you", NULL);
    assert(Ring_length(ring) == 4);

    assert(strcmp(Ring_get(ring, 0), "hello") == 0);
    assert(strcmp(Ring_get(ring, 3), "you") == 0);
    
    assert(strcmp(Ring_put(ring, 3, "you you"), "you") == 0);
    assert(strcmp(Ring_get(ring, 3), "you you") == 0);

    Ring_free(&ring);
    assert(ring == NULL);
}

static void
test_add_remove()
{
    Ring_T ring = Ring_ring((void*)100, (void*)200, (void*)300, (void*)400, NULL);
    Ring_addlo(ring, (void*)1000);
    assert(Ring_length(ring) == 5);
    assert(Ring_get(ring, 0) == (void*)1000);
    assert(Ring_get(ring, 4) == (void*)400);

    Ring_add(ring, 1, (void*)2000);
    assert(Ring_remlo(ring) == (void*)2000);
    Ring_add(ring, -Ring_length(ring), (void*)2000);
    assert(Ring_remlo(ring) == (void*)2000);

    Ring_add(ring, 0, (void*)3000);
    assert(Ring_remhi(ring) == (void*)3000);
    Ring_add(ring, Ring_length(ring) + 1, (void*)3000);
    assert(Ring_remhi(ring) == (void*)3000);

    // 1000 100 200 300 400
    assert(Ring_length(ring) == 5);
    assert(Ring_get(ring, 0) == (void*)1000);
    assert(Ring_get(ring, 4) == (void*)400);

    Ring_add(ring, 3, (void*)4000);
    // 1000 100 4000 200 300 400
    assert(Ring_get(ring, 2) == (void*)4000);

    Ring_add(ring, -5, (void*)4001);
    // 1000 4001 100 4000 200 300 400
    assert(Ring_get(ring, 1) == (void*)4001);
    assert(Ring_get(ring, 3) == (void*)4000);

    assert(Ring_remove(ring, 3) == (void*)4000);
    assert(Ring_remove(ring, 1) == (void*)4001);
    assert(Ring_remove(ring, 0) == (void*)1000);

    // 100 200 300 400
    assert(Ring_length(ring) == 4);
    assert(Ring_get(ring, 0) == (void*)100);
    assert(Ring_get(ring, 3) == (void*)400);

    Ring_free(&ring);
    assert(ring == NULL);
}

static void
test_rotate()
{
    // 100 200 300 400
    // 0   1   2   3
    // -4 -3  -2  -1
    Ring_T ring = Ring_ring((void*)100, (void*)200, (void*)300, (void*)400, NULL);

    Ring_rotate(ring, 2);
    // 300 400 100 200
    assert(Ring_get(ring, 0) == (void*)300);
    assert(Ring_get(ring, 3) == (void*)200);
    
    Ring_rotate(ring, -3);
    // 400 100 200 300
    assert(Ring_get(ring, 0) == (void*)400);
    assert(Ring_get(ring, 3) == (void*)300);

    Ring_free(&ring);
}

int main()
{
    test();
    test_add_remove();
    test_rotate();
    return 0;
}
